/*
 * @Date: 2022-03-16 15:05:51
 * @Version: 1.0.0
 * @Author: minichen
 * @Description: CustomOverlay
 * @FilePath: \bmap-libs\src\plugin\CustomOverlay.js
 * @LastEditTime: 2022-03-16 22:11:24
 * @LastEditors: minichen
 */
export default function (BMap) {
  function CustomOverlay() {
    // 禁止覆盖物在map.clearOverlays方法中被清除
    this.enableMassClear = false;

    // clearoverlays事件回调
    this._clearoverlaysEventCallback = function () {
      this._map.removeOverlay(this);
    }.bind(this);

    // 观察者
    this._observer = {};
  }

  // 继承Overlay原型
  CustomOverlay.prototype = new BMap.Overlay();
  CustomOverlay.prototype.constructor = CustomOverlay;

  /**
   * @description: 添加clearoverlays事件
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._addClearoverlaysEvent = function () {
    this._map.on('clearoverlays', this._clearoverlaysEventCallback);
  };

  /**
   * @description: 移除clearoverlays事件
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._removeClearoverlaysEvent = function () {
    this._map.off('clearoverlays', this._clearoverlaysEventCallback);
  };

  /**
   * @description: 添加自定义内容到节点
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._appendContainerContent = function () {
    let content = this._content;

    // 用户输入的内容是字符串，需要转化成dom节点
    if (typeof content == 'string') {
      const div = document.createElement('div');
      div.innerHTML = content;

      if (div.childNodes.length == 1) {
        content = div.removeChild(div.firstChild);
      } else {
        const fragment = document.createDocumentFragment();
        while (div.firstChild) {
          fragment.appendChild(div.firstChild);
        }
        content = fragment;
      }
    } else if (content instanceof HTMLElement) {
      // ...
    } else {
      console.error('Param content should be a string or HTMLElement');
      return;
    }

    this._container.innerHTML = '';
    this._container.appendChild(content);
  };

  /**
   * @description: 获取节点尺寸
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._getContainerSize = function () {
    this._size = new BMap.Size(this._container.offsetWidth, this._container.offsetHeight);
  };

  /**
   * @description: 添加节点
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._addDom = function () {
    // 防止多次调用重复添加
    this._removeDom();

    // floatPane: 800, markerMouseTarget: 700, floatShadow: 600, labelPane: 500, markerPane: 400
    let pane = this._options ? this._options.pane : 'markerPane';
    pane = this._map.getPanes()[pane] || this._map.getPanes().markerPane;
    pane.appendChild(this._container);
  };

  /**
   * @description: 移除节点
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._removeDom = function () {
    if (this._container && this._container.parentNode) {
      this._container.parentNode.removeChild(this._container);
    }
  };

  /**
   * @description: 添加事件
   * @param {*} type
   * @param {*} listener
   * @return {*}
   */
  CustomOverlay.prototype.on = function (type, listener) {
    if (!this._observer[type]) {
      this._observer[type] = [];
    }

    let list = this._observer[type];
    if (list.indexOf(listener) !== -1) return;
    list.push(listener);

    if (this._container) {
      this._bindEvent(type, listener);
    }
  };

  /**
   * @description: 移除事件
   * @param {*} type
   * @param {*} listener
   * @return {*}
   */
  CustomOverlay.prototype.off = function (type, listener) {
    if (!this._observer[type] || this._observer[type].indexOf(listener) === -1) return;
    this._observer[type] = this._observer[type].filter((lt) => lt !== listener);

    if (this._container) {
      this._unbindEvent(type, listener);
    }
  };

  /**
   * @description: 绑定事件
   * @param {*} type
   * @param {*} listener
   * @return {*}
   */
  CustomOverlay.prototype._bindEvent = function (type, listener) {
    this._container.addEventListener(type, listener, false);
  };

  /**
   * @description: 解绑事件
   * @param {*} type
   * @param {*} listener
   * @return {*}
   */
  CustomOverlay.prototype._unbindEvent = function (type, listener) {
    this._container.removeEventListener(type, listener, false);
  };

  /**
   * @description: 批量事件处理
   * @param {*} handler
   * @return {*}
   */
  CustomOverlay.prototype._patchEventHandle = function (handler) {
    Object.entries(this._observer).forEach(([type, listeners]) => {
      listeners.forEach((listener) => {
        handler.call(this, type, listener);
      });
    });
  };

  /**
   * @description: 覆盖物可见性
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype.isVisible = function () {
    return this._visible === undefined || this._visible;
  };

  /**
   * @description: 设置覆盖物层级
   * @param {*} zIndex
   * @return {*}
   */
  CustomOverlay.prototype.setZIndex = function (zIndex) {
    if (typeof zIndex !== 'number') return;

    if (!this._options) {
      this._options = {};
    }
    this._options.zIndex = zIndex;

    if (this._container) {
      this._container.style.zIndex = zIndex;
    }
  };

  /**
   * @description: 获取覆盖物层级
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype.getZIndex = function () {
    return this._options ? this._options.zIndex : null;
  };

  /**
   * @description: 封装的draw（确保draw方法在remove后不会被调用）
   * @param {*}
   * @return {*}
   */
  CustomOverlay.prototype._draw = function () {
    if (!this._removed) {
      this.draw();
    }
  };

  /**
   * @description: 返回标注的地理坐标
   * @return {*}
   */
  CustomOverlay.prototype.getPosition = function () {
    return this._point;
  };

  return CustomOverlay;
}
